/*
Copyright 2008 Ian Thomas

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.wildwinter.anthx;

import org.apache.tools.ant.Task;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.taskdefs.ExecTask;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.condition.Os;
import org.apache.tools.ant.types.Path;

import java.io.*;
import java.util.*;
import java.util.regex.*;

public class HaxeEnv extends Task 
{
    static File haxePath=null;
    static File nekoPath=null;
	
    private static Environment.Variable haxePathEnv=null;
    private static Environment.Variable nekoPathEnv=null;
    
    private static File haxeExec;
    private static File nekoExec;
    private static File haxelibExec;
    
	public HaxeEnv()
	{
	}

    public void setHaxePath(File value)
    {
	    haxePath=value;
	    if (value!=null)
	    {
		    haxePathEnv=new Environment.Variable();
		    haxePathEnv.setKey("HAXEPATH");
		    haxePathEnv.setFile(value);

		    if (Os.isFamily(Os.FAMILY_WINDOWS))
		    {
		    	haxeExec=new File(haxePath,"haxe.exe");
		    	haxelibExec=new File(haxePath,"haxelib.exe");
	    	}
			else
			{
				haxeExec=new File(haxePath,"haxe");
				haxelibExec=new File(haxePath,"haxelib");
			}
	    }
	    else
	    {
		    haxePathEnv=null;
		    haxeExec=null;
		    haxelibExec=null;
	    }
    }
    
    public void setNekoPath(File value)
    {
	    nekoPath=value;
	    if (value!=null)
	    {
		    nekoPathEnv=new Environment.Variable();
		    nekoPathEnv.setKey("NEKO_INSTPATH");
		    nekoPathEnv.setFile(value);
		    
		    if (Os.isFamily(Os.FAMILY_WINDOWS))
		    	nekoExec=new File(nekoPath,"neko.exe");
			else
				nekoExec=new File(nekoPath,"neko");
	    }
	    else
	    {
		    nekoPathEnv=null;
		    nekoExec=null;
	    }
    }
   
    public static ExecTask createHaxelibTask(Project project) throws BuildException
    {
	    ExecTask exec=(ExecTask)project.createTask("exec");
	    
	    addEnvironmentTo(project,exec);
			
		if (haxelibExec!=null)
		{
			if (!haxelibExec.exists())
				throw new BuildException("Can't find haxelib executable:"+haxelibExec);
			exec.setExecutable(haxelibExec.getAbsolutePath());
		} 
		else
			exec.setExecutable("haxelib");
		return exec;
    }
    
    public static ExecTask createHaxeTask(Project project) throws BuildException
    {
	    ExecTask exec=(ExecTask)project.createTask("exec");
	    
	    addEnvironmentTo(project,exec);
			
		if (haxeExec!=null)
		{
			if (!haxeExec.exists())
				throw new BuildException("Can't find haxe executable:"+haxeExec);
			exec.setExecutable(haxeExec.getAbsolutePath());
		} 
		else
			exec.setExecutable("haxe");
		return exec;
    }
    
    public static ExecTask createNekoTask(Project project) throws BuildException
    {
	    ExecTask exec=(ExecTask)project.createTask("exec");
	    
	    addEnvironmentTo(project,exec);
			
		if (nekoExec!=null)
		{
			if (!nekoExec.exists())
				throw new BuildException("Can't find neko executable:"+nekoExec);
			exec.setExecutable(nekoExec.getAbsolutePath());
		} 
		else
			exec.setExecutable("neko");
		return exec;
    }
    
    private static void addEnvironmentTo(Project project,ExecTask task)
    {
	    Path path=new Path(project);
	    
		if (haxePathEnv!=null)
		{
			task.addEnv(haxePathEnv);
			path.createPathElement().setLocation(haxePath);
		}
		
		if (nekoPathEnv!=null)
		{
			task.addEnv(nekoPathEnv);
			path.createPathElement().setLocation(nekoPath);
		}

		Vector envVars = Execute.getProcEnvironment();
		Enumeration e = envVars.elements();
		
		
		while (e.hasMoreElements()) 
		{
			String line = (String) e.nextElement();
			if (line.startsWith("PATH=")||line.startsWith("Path="))
			{
			    Path subPath = new Path(project,line.substring("PATH=".length()));
			    path.add(subPath);
			    break;
			}
		}
		
		Environment.Variable pathEnv=new Environment.Variable();
		pathEnv.setKey("PATH");
		pathEnv.setPath(path);
		
		task.addEnv(pathEnv);
		
		task.setFailonerror(true);
	}
	
	public static void addNekoPath(ExecTask task,File elem)
	{
		Project project=task.getProject();
		Path path=new Path(project);
		
		Vector envVars=Execute.getProcEnvironment();
		Enumeration e=envVars.elements();
		
		while (e.hasMoreElements())
		{
			String line = (String) e.nextElement();
			if (line.startsWith("NEKOPATH="))
			{
			    Path subPath = new Path(project,line.substring("NEKOPATH=".length()));
			    path.add(subPath);
			    break;
			}
		}
		
		Path subPath=new Path(project,elem.getAbsolutePath());
		path.add(subPath);
		
		Environment.Variable pathEnv=new Environment.Variable();
		pathEnv.setKey("NEKOPATH");
		pathEnv.setPath(path);
		
		task.addEnv(pathEnv);
	}
	
	public static void addNekoLibPath(ExecTask task, String lib)
	{
		Project project=task.getProject();
		File libPath=getHaxelibPath(project,lib);
		
		if (Os.isFamily(Os.FAMILY_WINDOWS))
			libPath=new File(libPath,"ndll/Windows");
		else if (Os.isFamily(Os.FAMILY_MAC))
			libPath=new File(libPath,"ndll/Mac");
		else
			libPath=new File(libPath,"ndll/Linux");
			
		if (libPath.exists())
			HaxeEnv.addNekoPath(task,libPath);
	}
    
    public void execute() 
    {

    }
    
    private static int _nextHXLIBProp=1;
    
    public static File getHaxelibPath(Project project, String lib)
    {	    	
	    ExecTask haxelib=createHaxelibTask(project);
	    haxelib.createArg().setValue("path");
	    haxelib.createArg().setValue(lib);
	    
	    String prop="haxelibpath_"+_nextHXLIBProp;
	    _nextHXLIBProp++;
	    
        haxelib.setOutputproperty(prop);
	    haxelib.execute();
	    
	    String out=project.getProperty(prop);
	    Pattern p=Pattern.compile("^([^-][^L].*)$",Pattern.MULTILINE);
	    Matcher m=p.matcher(out);
	    if (m.find())
	    {
		    String path=m.group(1);
		    File libPath=new File(path);
		    return libPath;
	    }
	    else
	    {
		    throw new BuildException("Can't find haxelib path for:"+lib);
	    }
    }
}